unit UCreateUUID;

interface

uses
  SysUtils, Winsock, Windows, DateUtils, StrUtils, SyncObjs;

  function GenerateUUID(): String;
  function GenerateOrderID(): String;
  function GetComputerName: String;
  function GetComputerIP: String;
  procedure InitUUIDGenerate();

const
  SEP = '';

var
  UUIDOrderCount: Integer;
  SystemStartMilliSeconds: String;
  CodePoolCS: TCriticalSection;

const
  BEGIN_DATE = 25569.3333333333;

implementation

procedure InitUUIDGenerate;
var
  lms: Int64;
begin
  lms := MilliSecondsBetween(now,BEGIN_DATE);
  SystemStartMilliSeconds := IntToHex((lms shr 8),8);
  SystemStartMilliSeconds := LeftStr(SystemStartMilliSeconds,8);
  UUIDOrderCount := 0;
end;

function GetComputerName: string;
var
  Size: DWord;
begin
  Size := MAX_COMPUTERNAME_LENGTH + 1;
  SetLength(Result,Size);
  Windows.GetComputerName(PChar(Result),Size);
  SetLength(Result,StrLen(PChar(Result)));
end;

function GetHostEnt: PHostEnt;
var
  wd: TWSAData;
  HoustName: AnsiString;
begin
  Result := Nil;
  if WSAStartup(MakeWord(2,0),wd) <> 0 then
    raise Exception.Create('Initialization "WinSock" Error!')
  else
    try
      SetLength(HoustName,255);
      if GetHostName(PAnsiChar(HoustName),255) <> 0 then
        raise Exception.Create('cant get Loacal Name!');
      SetLength(HoustName,StrLen(PAnsiChar(HoustName)));
      Result := gethostbyname(PAnsiChar(HoustName));
      if nil = Result then
        raise Exception.Create('cant get Loacal IP Address!');
      //change mulit IPs
    finally
      WSACleanup;
    end;
end;

function GetComputerIP: String;
begin
  Result := Trim(inet_ntoa(PInAddr(GetHostEnt.h_addr^)^));
end;

function GetComputerIP8Hex: String;
begin
  try
    Result := Trim(IntToHex(PInAddr(GetHostEnt.h_addr^).S_addr,8));
    Result := LeftStr(Result,8);
  except
    Result := '00000000';
  end;
end;

function GetHiTimeHex(): String;
var
  lms: Int64;
begin
  lms := MilliSecondsBetween(now,BEGIN_DATE);
  Result := IntToHex((lms shr 32),4);
  Result := LeftStr(Result,4);
end;


function GetLoTimeHex(): String;
var
  lms: Int64;
begin
  lms := MilliSecondsBetween(now,BEGIN_DATE);
  Result := IntToHex(lms,8);
  Result := LeftStr(Result,8);
end;

function GetOrderCountHex(): String;
begin
  Result := IntToHex(UUIDOrderCount,4);
  Result := LeftStr(Result,4);
  Inc(UUIDOrderCount);
end;

function GenerateUUID(): String;
begin
  CodePoolCS.Enter;
  try
    Result := GetComputerIP8Hex + SEP + SystemStartMilliSeconds + SEP +
      GetHiTimeHex + SEP + GetLoTimeHex + SEP + GetOrderCountHex;
  finally
    CodePoolCS.Leave;
  end;
end;

function GenerateOrderID(): String;
begin
  CodePoolCS.Enter;
  try
    Result := IntToHex(UUIDOrderCount,32);
    Result := LeftStr(Result,32);
    Inc(UUIDOrderCount);
  finally
    CodePoolCS.Leave;
  end;
end;

initialization
  InitUUIDGenerate();
  CodePoolCS := TCriticalSection.Create;

finalization
  CodePoolCS.Free;

end.
